from baidubce.services.bts.model import ScanArgs
from onething_client import DeviceOperations, DeviceAuthorization, IdentityInfo
from celery.utils.log import get_task_logger
from requests import HTTPError

from monitor_tasks.celery import app
from monitor_tasks.prometheus_remote_write import report_device_network_status_to_prometheus, Label, NetworkStatus
from monitor_tasks.fetch_monitoring_data.fetch_device_info_tasks import query_device_list
from monitor_tasks.table_storage import table_client

logger = get_task_logger(__name__)


@app.task
def scan_device_task():
    scan_args = ScanArgs()
    try:
        response = table_client.scan(b'flow_guardian', b'device_info', scan_args)
        for row in response.result:
            device_info = {}
            for cell in row.cells:
                device_info.update({cell.column: cell.value})
            fetch_onething_device_network_status.delay(device_info)
    except Exception as ex:
        logger.error(ex)


@app.task(expires=15)
def fetch_onething_device_network_status(device_info):
    device_authorization = create_device_authorization(device_info)
    device_operations = DeviceOperations(device_authorization)
    try:
        response = device_operations.fetch_pppoe_network_info()
        logger.info(response)
        if "errcode" in response and response["errcode"] == 0:
            recordtime = response["recordtime"]
            for multidial in response['multidial']:
                network_status = create_network_status(multidial, recordtime)
                labels = create_labels(device_info, multidial)
                report_device_network_status_to_prometheus(network_status, labels)
    except HTTPError as he:
        query_device_list.delay(device_info['userid'], device_info['rk'], device_info['ak'], device_authorization.sn)
        logger.error(he)


def create_labels(device_info, multidial):
    return Label(
        broadband_number=multidial.get("username", "null"),
        vlan_id=multidial['vlanid'],
        network_type=multidial['proto'],
        network_interface=multidial['nic'],
        account_number=device_info['userid'],
        device_number=device_info['sn'],
        province=device_info['province'],
        telecom_carriers=device_info['isp'],
        device_model=device_info['deviceType'],
        device_group=device_info.get('deviceGroup', 'null'),
        business_type=device_info.get('bizType', 'null')
    )


def create_network_status(multidial, recordtime):
    return NetworkStatus(
        uplink_bandwidth_usage=int(multidial['upspeed']),
        downlink_bandwidth_usage=int(multidial['downspeed']),
        network_received_total=int(multidial['recvbytes']),
        network_transmitted_total=int(multidial['sentbytes']),
        timestamp=recordtime * 1000
    )


def create_device_authorization(device_info):
    identity_info = IdentityInfo(
        userid=device_info['userid'],
        ak=device_info['ak'],
        rk=device_info['rk']
    )
    return DeviceAuthorization(
        sn=device_info['sn'],
        expire=device_info['expire'],
        sign=device_info['sign'],
        identity_info=identity_info
    )
